package cn.com.libertymutual.sys.service.impl;

import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.hibernate.HibernateException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import cn.com.libertymutual.core.base.dto.UserInfo;
import cn.com.libertymutual.core.exception.CustomJDBCException;
import cn.com.libertymutual.core.exception.CustomLangException;
import cn.com.libertymutual.core.exception.LangExceptionEnums;
import cn.com.libertymutual.core.redis.util.RedisUtils;
import cn.com.libertymutual.core.util.Constants;
import cn.com.libertymutual.core.web.ServiceResult;
import cn.com.libertymutual.sys.bean.SysMenu;
import cn.com.libertymutual.sys.bean.SysRoleMenuRes;
import cn.com.libertymutual.sys.bean.SysUserMenuRes;
import cn.com.libertymutual.sys.dao.ISysMenuResDao;
import cn.com.libertymutual.sys.dao.ISysRoleMenuDao;
import cn.com.libertymutual.sys.dao.ISysRoleMenuResDao;
import cn.com.libertymutual.sys.dao.ISysUserMenuDao;
import cn.com.libertymutual.sys.dao.ISysUserMenuResDao;
import cn.com.libertymutual.sys.service.api.IInitSharedMemory;
import cn.com.libertymutual.sys.service.api.ISystemService;
import cn.com.libertymutual.sys.vo.MenuConvert;
import cn.com.libertymutual.sys.vo.MenuInfoVO;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

@Service("systemService")
public class SystemServiceImpl implements ISystemService {

	
	private Logger log = LoggerFactory.getLogger(getClass());
	@Resource RedisUtils redisUtils;
	@Autowired ISysRoleMenuDao  roleMenuDao;
	@Autowired ISysRoleMenuResDao  roleMenuResDao;
	@Autowired ISysUserMenuDao  userMenuDao;
	@Autowired ISysUserMenuResDao  userMenuResDao;
	@Autowired ISysMenuResDao  menuResDao;
	@Autowired
	private IInitSharedMemory  initSharedMemory;
	@Override
	@Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true)
	public void login( HttpServletRequest request, Integer fmenuId, ServiceResult result ) throws CustomLangException,CustomJDBCException {
		try {
			HttpSession session = request.getSession();
			//session 中获取用户信息
			UserInfo userInfo = (UserInfo)session.getAttribute(Constants.USER_INFO_KEY);
			
			if( userInfo == null || userInfo.getTokenId() == null ) {
				throw  new CustomLangException(LangExceptionEnums.SECURITY_TOKEN_EXCEPTION);
			}
			
			
			//创建返回的map
			Map<String, Object> map = Maps.newHashMap();
			//创建返回的用户基本信息
			Map<String, Object> userMap = Maps.newHashMap();
			
			userMap.put("id", userInfo.getUserId() );
			userMap.put("name", userInfo.getUserName() );
			userMap.put("branchNo", userInfo.getBranchNo() );//选择的机构
			userMap.put("branchName", userInfo.getBranchName() );
			userMap.put("departmentCode", userInfo.getDepartmentCode() );
			userMap.put("departmentName", userInfo.getDepartmentName() );
			userMap.put("tokenId",userInfo.getTokenId() );
			
			ServiceResult r = new ServiceResult();
			getAccessMenuInfo(fmenuId, r);
			map.put("menu", r.getResult() );
			
			/*if( userInfo.getLoginComCodeList().size() == 1 || appFlag != null ) { 
				//如果appFlag 未传,则说明是业务端登录获取菜单
				//否则是在后端登录的
				if( appFlag == null ) {
					 map.put("menu", menuDao.findSysMenu( userInfo.getRoleId(), userInfo.getUseRiskCode(), 0) );
				}
				else {
				//}
			}
			else {
				//add by bob.kuang 20160826 增加机构选择
				userMap.put("loginComCodeList", userInfo.getLoginComCodeList() );
				//end
			}*/

			map.put("user", userMap);
			
			//获取登录的语言信息
			Locale locale = LocaleContextHolder.getLocale();  
			String language= locale.toString();
			map.put("language", language);
			result.setResult( map );
		 
		}catch(Exception e){
			log.error(e.getMessage(),e);
			//将捕获到的异常转换为自定义异常抛出
			throw new CustomLangException(e);
		}
	}


	@Override
	public void getAccessMenuInfo(Integer fmenuId, ServiceResult result) throws CustomLangException  {

		ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
		if( servletRequestAttributes == null || servletRequestAttributes.getRequest() == null ) {
			throw new CustomLangException("获取Request失败");
		}

		try {
			UserInfo userInfo = (UserInfo)servletRequestAttributes.getRequest().getSession(true).getAttribute(Constants.USER_INFO_KEY);
			//如果用户权限不为空,则查询菜单
			if(userInfo != null && !userInfo.getRoleId().isEmpty()){

			  List<MenuInfoVO> gg =	this.getAccessMenuInfo(fmenuId, userInfo.getRoleId(),userInfo.getUserId());
					  result.setResult( gg); 
				}
			}catch(HibernateException e){
			log.error(e.getMessage(),e);
			throw new CustomJDBCException(e);
		}catch(Exception e){
			log.error(e.getMessage(),e);
			//将捕获到的异常转换为自定义异常抛出
			throw new CustomLangException(e);
		}
	} 
	@Override
	public List<MenuInfoVO> getAccessMenuInfo(Integer fmenuId ,List<String> roleIds ,String userId) throws CustomLangException  {
		List<MenuInfoVO> gg =null;
		try {
			Map<String, SysMenu> menuMap = (Map<String, SysMenu>)redisUtils.get( Constants.MENU_INFO_KEY ) ;
			if( menuMap == null || menuMap.isEmpty()) {
				menuMap = initSharedMemory.initSysMenu();
			}
			
			//测试使用
			menuMap = initSharedMemory.initSysMenu();
			
			Map<String, List<Integer>> menuMapRel = (Map<String, List<Integer>>)redisUtils.get( Constants.MENU_REL_INFO_KEY ) ;
			List<Integer> msd = menuMapRel.get("1"); 
			msd.toString();
			//UserInfo userInfo = (UserInfo)((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest().getSession().getAttribute(Constants.USER_INFO_KEY);
			//如果用户权限不为空,则查询菜单
			if(!roleIds.isEmpty()){
				String in_sql=getIn(  roleIds);
				//String sql = "SELECT DISTINCT t1.menuid FROM tb_sys_role_menu t1 INNER JOIN tb_sys_menu t2 ON t1.menuid=t2.menuid WHERE t1.roleid IN ("+in_sql+") GROUP BY t1.menuid ORDER BY t2.orderid";
				List<Integer> menuIdList  =Lists.newArrayList(); 
				List<Integer> tempList = null;// roleMenuDao.nativeQuery4Map(sql);
				//List<Integer> menuIdList = roleMenuDao.findRoleMenu( userInfo.getRoleId(), fmenuId == null ? -1 : fmenuId );
				//List<Map<String, Object>> list = menuDao.nativeQuery4Map(sql);
				tempList=  roleMenuDao.findRoleMenu(roleIds);
				List<Integer> userMenuIdList= userMenuDao.findUserMenu(userId);
				
				tempList.addAll(userMenuIdList);
				HashSet<Integer> h  =   new  HashSet<>(tempList);
			    menuIdList.addAll(h);
				MenuConvert mc = new MenuConvert();
				
				//String sidsql = "select DISTINCT MENUID , RESID from tb_sys_role_menu_res where roleId in ("+in_sql+") order by menuId";
				Map<Integer,List<String>> mResIdList = Maps.newHashMap(); 
				List<SysRoleMenuRes>  ress =roleMenuResDao.findByRoleid(roleIds);
				for(SysRoleMenuRes r : ress){
					Integer  menuId =	r.getMenuid();
					if(mResIdList.containsKey(menuId)){
						List<String> itemIdList = mResIdList.get(menuId);
						itemIdList.add(r.getResid());
					}else{
						List<String> itemIdList = Lists.newArrayList();
						itemIdList.add(r.getResid());
						mResIdList.put(menuId, itemIdList);
					}
				}
				
				
				List<SysUserMenuRes> menuRes =  userMenuResDao.findByUserid(userId);
				for(SysUserMenuRes r : menuRes){
					Integer  menuId =	r.getMenuid();
					if(mResIdList.containsKey(menuId)){
						List<String> itemIdList = mResIdList.get(menuId);
						itemIdList.add(r.getResid());
					}else{
						List<String> itemIdList = Lists.newArrayList();
						itemIdList.add(r.getResid());
						mResIdList.put(menuId, itemIdList);
					}
				}
				
				
				
				//Map<Integer,List<String>> mResIdList = mc.convertResList( menuDao.nativeQuery4Map(sidsql) ); 
				gg = mc.genMenuTree(menuMap, menuIdList, menuMapRel, mResIdList, fmenuId) ;
			}
		}catch(HibernateException e){
			log.error(e.getMessage(),e);
			throw new CustomJDBCException(e);
		}catch(Exception e){
			log.error(e.getMessage(),e);
			//将捕获到的异常转换为自定义异常抛出
			throw new CustomLangException(e);
		}
		return gg;
	}

	
	private String getIn(List<String> initems) {
		StringBuilder buffer = new StringBuilder();
		for( String item : initems ){
			buffer.append("'") .append(item).append("'"); 
		}
		return buffer.toString();
	}


	@Override
	@Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true)
	public JSONArray getJsonMenuInfo( String uiType, Integer menuId, String execType, String roleId ) throws CustomLangException  {

		try {
			JSONObject obj = new JSONObject();
			obj.put("id", 0);
			obj.put("ztree".equals(uiType)?"name":"text", "顶级菜单");
			obj.put("open", true);
			obj.put("drag", false);
			
			MenuConvert mc = new MenuConvert();
			
			List<Integer> menuIdList = null;
			Map<Integer,List<String>> menuResIdListMap = null;
			if( "modif".equals( execType ) ) {
				/*menuIdList = roleMenuDao.findMenuIdList(roleId);
				menuResIdListMap = mc.convertResList( menuResDao.findMenuResIdList(roleId) );
				*/
			}
			
			Map<Integer, SysMenu> menuMap = (Map<Integer, SysMenu>)redisUtils.get( Constants.MENU_INFO_KEY );
			
			Map<Integer,List<SysMenu>> levelMenuMap = mc.convertyMenuLevel(menuMap);
			
			JSONArray b = mc.getAllChildrenMenuInfo( levelMenuMap, uiType, 0, true, menuId, menuIdList, menuResIdListMap );
			
			JSONArray a = new JSONArray();
			obj.put("children", b);
			
			a.add( obj );
			
			return a;
		}catch(HibernateException e){
			log.error(e.getMessage(),e);
			throw new CustomJDBCException(e);
		}catch(Exception e){
			log.error(e.getMessage(),e);
			//将捕获到的异常转换为自定义异常抛出
			throw new CustomLangException(e);
		}
	}
 
 
}
